package com.kuang.single;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

/**
 * @author Administrator
 * @date 2021/5/27 15:00
 * Description:懒汉式 道高一尺,魔高一丈
 * https://www.bilibili.com/video/BV1B7411L7tE?t=1418&p=33
 */
public class LazyMan {
    private static volatile LazyMan lazyMan;

    private static boolean flag = false;

    private LazyMan(){
        synchronized (LazyMan.class) {
            if (!flag) {
                flag = true;
            } else {
                throw new RuntimeException("不要试图使用反射破坏异常");
            }
        }
    }

    //双重检测锁模式的 懒汉式单例 DCL懒汉式
    //DCL: Double Check Lock
    private static LazyMan getInstance() {
        if (lazyMan == null) {
            synchronized (LazyMan.class) {
                if (lazyMan == null) {
                    lazyMan = new LazyMan();
                }
            }
        }
        return lazyMan;
    }

    //反射
    public static void main(String[] args) throws Exception {
//        LazyMan instance1 = LazyMan.getInstance();
        Field flagField = LazyMan.class.getDeclaredField("flag");
        flagField.setAccessible(true);

        Constructor<LazyMan> declaredConstructor = LazyMan.class
                .getDeclaredConstructor();
        declaredConstructor.setAccessible(true);
        LazyMan instance1 = declaredConstructor.newInstance();

        flagField.set(instance1, false);

        LazyMan instance2 = declaredConstructor.newInstance();
        System.out.println(instance1);
        System.out.println(instance2);
    }
    /**
     * lazyMan = new LazyMan()的过程：
     * 1、分配内存空间
     * 2、执行构造方法，初始对象
     * 3、把这个对象指向这个空间
     *
     * 加入了volatile关键字以确保上述步骤不被打乱，
     * 也就是禁止指令重排
     * 123
     * 132 A线程
     *     B线程  //此时lazyMan还没有完成构造
     */
}
